<html>
<head>
	<meta charset="utf-8">
	<title>JavaScript 严格模式详解</title>
	<link rel="stylesheet" type="text/css" href="css/style.css">
</head>
<body>
<div class="content" style="background-image: url(img/bga.jpeg);">
	<div class="box">
		<h2>严格模式详解</h2>
		<h4>严格模式是一种特殊的运行模式,
它修复了部分语言上的不足，提供更强的错误检查，并增强安全性。
</h4>
		<ul class="first">
			<li>概述:除了正常运行模式，ECMAscript5添加了第二种运行模式："严格模式"（strict mode）。顾名思义，这种模式使得Javascript在更严格的条件下运行。
				<div class="font">"严格模式"的目的</div>
				<ul class="second">
					<li>消除Javascript语法的一些不合理、不严谨之处，减少一些怪异行为;</li>
					<li>消除代码运行的一些不安全之处，保证代码运行的安全；</li>
					<li>提高编译器效率，增加运行速度；</li>
					<li>为未来新版本的Javascript做好铺垫。</li>
				</ul>
				<div class="font">"严格模式"体现了Javascript更合理、更安全、更严谨的发展方向，包括IE 10在内的主流浏览器，都已经支持它，许多大项目已经开始全面拥抱它。<br/>另一方面，同样的代码，在"严格模式"中，可能会有不一样的运行结果；一些在"正常模式"下可以运行的语句，在"严格模式"下将不能运行。</div>
			</li>
			<li>进入标志
				<div class="font">进入"严格模式"的标志，是下面这行语句：　"use strict";</div>
				<div class="example">要注意的是：老版本的浏览器会把它当作一行普通字符串，加以忽略。</div>
			</li>
			<li>"严格模式"的两种调用方法
				<ul class="second">
					<li>针对整个脚本文件<br/>
						将"use strict"放在脚本文件的第一行，则整个脚本都将以"严格模式"运行。如果这行语句不在第一行，则无效，整个脚本以"正常模式"运行。如果不同模式的代码文件合并成一个文件，这一点需要特别注意。
						<div class="font">严格地说，只要前面不是产生实际运行结果的语句，"use strict"可以不在第一行，比如直接跟在一个空的分号后面。</div>
						<pre class="example">
						如：
							< script >
						　　　　"use strict";
						　　　　console.log("这是严格模式。");
						　　< / script >
						</pre>
					</li>
					<li>针对单个函数<br/>
						<div class="font">将"use strict"放在函数体的第一行，则整个函数以"严格模式"运行。</div>
						<pre class="example">

						function strict(){
					　　　　"use strict";
					　　　　return "这是严格模式。";
					　　}

					　　function notStrict() {
					　　　　return "这是正常模式。";
					　　}
						</pre>
					</li>
					<li> 脚本文件的变通写法<br/>
						<div class="font">因为第一种调用方法不利于文件合并，所以更好的做法是，借用第二种方法，将整个脚本文件放在一个立即执行的匿名函数之中。</div>
						<pre class="example">

						(function (){

					　　　　"use strict";

					　　 })();
						</pre>
					</li>
				</ul>
			</li>
			<li>语法和行为改变
				<ul class="second">
					<li>全局变量显式声明: 在正常模式中，如果一个变量没有声明就赋值，默认是全局变量。严格模式禁止这种用法，全局变量必须显式声明。
					<pre class="example">
						"use strict";
					　　v = 1; // 报错，v未声明
					　　for(i = 0; i < 2; i++) { // 报错，i未声明
					　　}
					</pre>
					<span class="font">由此可见，严格模式下，变量都必须先用var命令声明，然后再使用。</span>
					</li>
					<li>静态绑定:Javascript语言的一个特点，就是允许"动态绑定"，即某些属性和方法到底属于哪一个对象，不是在编译时确定的，而是在运行时（runtime）确定的。<br/>严格模式对动态绑定做了一些限制。某些情况下，只允许静态绑定。也就是说，属性和方法到底归属哪个对象，在编译阶段就确定。这样做有利于编译效率的提高，也使得代码更容易阅读，更少出现意外。<br/>具体来说，涉及以下几个方面。
					<pre class="example">
						<div class="font">禁止使用with语句：因为with语句无法在编译时就确定，属性到底归属哪个对象。</div>
						"use strict";
						　　var v = 1;
						　　with (o){ // 语法错误 
						　　　　v = 2;
						　	}
						<div class="font">创设eval作用域：正常模式下，Javascript语言有两种变量作用域（scope）：全局作用域和函数作用域。严格模式创设了第三种作用域：eval作用域。<br/>正常模式下，eval语句的作用域，取决于它处于全局作用域，还是处于函数作用域。<br/>严格模式下，eval语句本身就是一个作用域，不再能够生成全局变量了，它所生成的变量只能用于eval内部。</div>
						"use strict";
					　　var x = 2;
					　　console.info(eval("var x = 5; x")); // 5
					　　console.info(x); // 2
					</pre>
					</li>
				</ul>
			</li>
			<li>增强的安全措施
				<ul class="second">
					<li>禁止this关键字指向全局对象
						<pre class="example">
							function f(){
						　　　　return !this;
						　　} 
						　　// 返回false，因为"this"指向全局对象，"!this"就是false
						　　function f(){ 
						　　　　"use strict";
						　　　　return !this;
						　　} 
						　　// 返回true，因为严格模式下，this的值为undefined，所以"!this"为true。

						因此，使用构造函数时，如果忘了加new，this不再指向全局对象，而是报错。
							function f(){
						　　　　"use strict";
						　　　　this.a = 1;
						　　};
						　　f();// 报错，this未定义
						</pre>
					</li>
					<li>禁止在函数内部遍历调用栈
						<pre class="example">
							function f1(){
						　　　　"use strict";
						　　　　f1.caller; // 报错
						　　　　f1.arguments; // 报错
						　　}
						　　f1();
						</pre>
					</li>
				</ul>
			</li>
			<li>禁止删除变量：严格模式下无法删除变量。只有configurable设置为true的对象属性，才能被删除。
				<pre class="example">
					"use strict";
					　　var x;
					　　delete x; // 语法错误
					　　var o = Object.create(null, {'x': {
					　　　　　　value: 1,
					　　　　　　configurable: true
					　　}});
					　　delete o.x; // 删除成功
				</pre>
			</li>
			<li>显式报错:
				<pre class="example">
					"use strict";
					　　var x;
					　　delete x; // 语法错误
					　　var o = Object.create(null, {'x': {
					　　　　　　value: 1,
					　　　　　　configurable: true
					　　}});
					　　delete o.x; // 删除成功
				</pre>
			</li>
			<li>重名错误:
				<ul class="second">
					<li>对象不能有重名的属性:正常模式下，如果对象有多个重名属性，最后赋值的那个属性会覆盖前面的值。严格模式下，这属于语法错误。
						<pre class="example">
							"use strict";
							　　var o = {
							　　　　p: 1,
							　　　　p: 2
							　　}; // 语法错误
						</pre>
					</li>
					<li>函数不能有重名的参数：正常模式下，如果函数有多个重名的参数，可以用arguments[i]读取。严格模式下，这属于语法错误。
						<pre class="example">
							"use strict";
							　　function f(a, a, b) { // 语法错误
							　　　　return ;
							　　}
						</pre>
					</li>
				</ul>
			</li>
			<li>禁止八进制表示法</li>
			<li>arguments对象的限制：arguments是函数的参数对象，严格模式对它的使用做了限制。
				<ul class="second">
					<li>不允许对arguments赋值
						<pre class="example">

							"use strict";
						　　arguments++; // 语法错误
						　　var obj = { set p(arguments) { } }; // 语法错误
						　　try { } catch (arguments) { } // 语法错误
						　　function arguments() { } // 语法错误
						　　var f = new Function("arguments", "'use strict'; return 17;"); // 语法错误
						</pre>
					</li>
					<li>arguments不再追踪参数的变化
						<pre class="example">
						
							function f(a) {
						　　　　a = 2;
						　　　　return [a, arguments[0]];
						　　}
						　　f(1); // 正常模式为[2,2]
						　　function f(a) {
						　　　　"use strict";
						　　　　a = 2;
						　　　　return [a, arguments[0]];
						　　}
						　　f(1); // 严格模式为[2,1]
						</pre>
					</li>
					<li>禁止使用arguments.callee
						<pre class="example">
						
							"use strict";
							var f = function() { return arguments.callee; };
							　　f(); // 报错
						</pre>
					</li>
				</ul>
			</li>
			<li>函数必须声明在顶层
				<pre class="example">
					"use strict";
					　　if (true) {
					　　　　function f() { } // 语法错误
					　　}
					　　for (var i = 0; i < 5; i++) {
					　　　　function f2() { } // 语法错误
					　　}
				</pre>
			</li>
			<li>保留字:严格模式新增了一些保留字：implements, interface, let, package, private, protected, public, static, yield。
				<pre class="example">

					function package(protected) { // 语法错误
				　　　　"use strict";
				　　　　var implements; // 语法错误
				　　}
				</pre>
			</li>
		</ul>
	</div>
</div>
</body>
</html>